package com.clei.utils;

import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

/**
 * html 截取 util
 * 用于html内容屏蔽展示部分
 * 适用于简单html
 *
 * @author Y
 * @date 2024-11-19
 **/
public class HtmlCutUtil {

    /**
     * 无结束标签的tag set
     */
    private final static Set<String> NO_END_TAG_SET = new HashSet<>();

    /**
     * 累计行数的tag set
     */
    private final static Set<String> LINE_COUNT_TAG_SET = new HashSet<>();

    static {
        NO_END_TAG_SET.add("br");
        NO_END_TAG_SET.add("img");

        LINE_COUNT_TAG_SET.add("/h1");
        LINE_COUNT_TAG_SET.add("/h2");
        LINE_COUNT_TAG_SET.add("/h3");
        LINE_COUNT_TAG_SET.add("/h4");
        LINE_COUNT_TAG_SET.add("/h5");
        LINE_COUNT_TAG_SET.add("/h6");
        LINE_COUNT_TAG_SET.add("/p");
        LINE_COUNT_TAG_SET.add("/li");
    }

    /**
     * 截取
     *
     * @param html      html文本
     * @param lineCount 截取行数
     * @return html
     */
    public static String cut(String html, int lineCount) {
        char[] charArray = html.toCharArray();
        // 标签栈 用于补全结束标签
        Stack<String> stack = new Stack<>();
        // 当前行数
        int curCount = 0;
        // 结果
        StringBuilder resHtml = new StringBuilder(lineCount * 70);

        StringBuilder sb = null;
        boolean tagStart = false;
        for (char c : charArray) {
            resHtml.append(c);
            // 开始
            if (c == '<') {
                tagStart = true;
                sb = new StringBuilder();
                // 结束
            } else if (c == '>') {
                tagStart = false;
                if (null != sb) {
                    String tag = clean(sb.toString());
                    if (tag.startsWith("/")) {
                        stack.pop();
                    } else {
                        if (!NO_END_TAG_SET.contains(tag)) {
                            stack.push(tag);
                        }
                    }
                    // 计数
                    if (LINE_COUNT_TAG_SET.contains(tag)) {
                        curCount++;
                        // 到此为止
                        if (curCount >= lineCount) {
                            break;
                        }
                    }
                }
                // 标签内容
            } else if (tagStart) {
                sb.append(c);
            }
        }
        // 结束标签
        while (!stack.isEmpty()) {
            String endTag = "</" + stack.pop() + '>';
            resHtml.append(endTag);
        }
        return resHtml.toString();
    }

    /**
     * 标签属性清理
     *
     * @param tag tag
     * @return tag
     */
    private static String clean(String tag) {
        int spaceIndex = tag.indexOf(' ');
        if (-1 != spaceIndex) {
            return tag.substring(0, spaceIndex);
        }
        return tag;
    }
}
